package com.example.gokchinesefoodmappcdev.config;


import com.example.gokchinesefoodmappcdev.filter.JWTTokenAuthenticationFilter;
import com.example.gokchinesefoodmappcdev.filter.MerchantSecurityMetadataSource;
import com.example.gokchinesefoodmappcdev.filter.ValidateCodeFilter;
import com.example.gokchinesefoodmappcdev.handler.LoginFailHandler;
import com.example.gokchinesefoodmappcdev.handler.LoginSuccessHandler;
import com.example.gokchinesefoodmappcdev.handler.MyAccessDeniedHandler;
import com.example.gokchinesefoodmappcdev.handler.MyAuthenticationEntryPoint;
import com.example.gokchinesefoodmappcdev.service.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/*
* 基于方法的权限配置
* */

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyUserDetailsService userDetailService;

    @Autowired
    MerchantSecurityMetadataSource securityMetadataSource;

    @Autowired
    LoginSuccessHandler loginSuccessHandler;

    @Autowired
    LoginFailHandler loginFailHandler;

    @Autowired
    JWTTokenAuthenticationFilter jwtTokenAuthenticationFilter;


    @Autowired
    ValidateCodeFilter validateCodeFilter;

    @Autowired
    private MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Override
    public void configure(WebSecurity web) throws Exception {
        //忽略去登录页的请求，如果没有前后端分离，自定义了登录页时需要在此处配置
        web.ignoring().antMatchers( "/user/getValidateCode","/toIndexPage","/toLoginPage");
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers("/css/**", "/images/**", "/js/**","/favicon.ico","/temp/validateCode/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //1、获取Spring容器
        ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);

        http.apply(
                new UrlAuthorizationConfigurer<>(applicationContext))
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                                             @Override
                                             public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                                                 //设置用自定义的权限验证元数据对象
                                                 object.setSecurityMetadataSource(securityMetadataSource);
                                                 object.setRejectPublicInvocations(true);
                                                 return object;
                                             }
                                         }
                );

        //将自定义的验证码过滤器添加到UsernamePasswordAuthenticationFilter之前
        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);

        //将jwt 的过滤器放到之前
        http.addFilterBefore(jwtTokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        http.formLogin()
                .loginPage("/toLoginPage")
                .loginProcessingUrl("/rest/auth")
                .successHandler(loginSuccessHandler)
                .failureHandler(loginFailHandler)
                .and()
                // 异常处理
                .exceptionHandling()
                .authenticationEntryPoint(myAuthenticationEntryPoint)
                .accessDeniedHandler(myAccessDeniedHandler)
                .and()
                .authorizeRequests()
                //任何请求都需要认证
                .anyRequest()
                .authenticated()
                .and()
                .sessionManagement()
                //禁用security从session中获取信息
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        //关闭csrf防护
        http.csrf().disable();

        // 允许iframe加载页面
        http.headers().frameOptions().sameOrigin();

        //允许跨域
        http.cors().configurationSource(corsConfigurationSource());

    }
    /*
     * 添加的跨域配置对象
     * */
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 设置允许跨域的站点，不能设置为 *
        corsConfiguration.addAllowedOrigin("http://127.0.0.1:8848");
        // 设置允许跨域的http方法
        corsConfiguration.addAllowedMethod("*");
        // 设置允许跨域的请求头
        corsConfiguration.addAllowedHeader("*");
        // 允许带凭证
        corsConfiguration.setAllowCredentials(true);

        // 对所有的url生效
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //使用自定义的MyUserDetailsService，从数据库获取用户信息
        auth.userDetailsService(userDetailService);
    }



}
